package com.example.fw;

import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.example.tests.ContactData;
import com.example.tests.ContactDataRow;
import com.example.tests.ContactDataPhone;
import com.example.utils.SortedListOf;
import org.testng.Assert;

public class ContactHelper extends WebDriverHelperBase {
	 
	public static boolean CREATION = true;
	public static boolean MODIFICATION = false;
	enum Type{
		NameMailsPhones,
		NamePhones
	}

	public ContactHelper(ApplicationManager manager) {
		super(manager);
	}
	
	private SortedListOf<ContactDataRow> cachedContacts;
	private SortedListOf<ContactDataPhone> cachedContactPhones;
	//private SortedListOf<ContactDataRow> contactsRow;
    
	public SortedListOf<ContactDataRow> getContacts() {
		if (cachedContacts == null) {
			rebuildCacheContacts(Type.NameMailsPhones);
		}
		return cachedContacts;
	}
	
	public SortedListOf<ContactDataRow> getContactsData() {
		rebuildCacheContacts(Type.NamePhones);
		return cachedContacts;
	}
	
	public SortedListOf<ContactDataPhone> getPhonesData() {
		rebuildCachePrintPhones();
		return cachedContactPhones;
	}
	
	private void rebuildCacheContacts(Type t) {
		SortedListOf<ContactDataRow> cachedContacts = new SortedListOf<ContactDataRow>();
		manager.navigateTo().mainPage();
		List<WebElement> firstnames = driver.findElements(By.xpath("//tr[@name='entry']/td[2]"));
		List<WebElement> lastnames = driver.findElements(By.xpath("//tr[@name='entry']/td[3]"));
		List<WebElement> emails = driver.findElements(By.xpath("//tr[@name='entry']/td[4]"));
		List<WebElement> telephones = driver.findElements(By.xpath("//tr[@name='entry']/td[5]"));
		
		for (int i = 0; i < firstnames.size(); i++) {
			if (t == Type.NameMailsPhones) {
				cachedContacts.add(new ContactDataRow()
					.withFirstname(firstnames.get(i).getText())
					.withLastname(lastnames.get(i).getText()) 
					.withEmail(emails.get(i).getText())
					.withPhone(telephones.get(i).getText()));
				} else if (t == Type.NamePhones) {
					String firstName = firstnames.get(i).getText();
					String lastName = lastnames.get(i).getText();
					if (lastName.isEmpty() && (!firstName.isEmpty())) {
						lastName = firstName;
						firstName = "";
					}
					cachedContacts.add(new ContactDataRow()
						.withFirstname(firstName)
						.withLastname(lastName)
						.withPhone(telephones.get(i).getText()));
				}
			} 		 
	this.cachedContacts = cachedContacts;
	}
	
	public SortedListOf<ContactDataRow> getUIContacts() {	
		SortedListOf<ContactDataRow> contactsRow = new SortedListOf<ContactDataRow>();
		manager.navigateTo().mainPage();
		List<WebElement> firstnames = driver.findElements(By.xpath("//tr[@name='entry']/td[2]"));
		List<WebElement> lastnames = driver.findElements(By.xpath("//tr[@name='entry']/td[3]"));
		List<WebElement> emails = driver.findElements(By.xpath("//tr[@name='entry']/td[4]"));
		List<WebElement> telephones = driver.findElements(By.xpath("//tr[@name='entry']/td[5]"));
		
		for (int i = 0; i < firstnames.size(); i++) {
			contactsRow.add(new ContactDataRow()
				.withFirstname(firstnames.get(i).getText())
				.withLastname(lastnames.get(i).getText()) 
				.withEmail(emails.get(i).getText())
				.withPhone(telephones.get(i).getText()));
			} 				 
		return contactsRow;
	}
	
	private void rebuildCachePrintPhones() {
		SortedListOf<ContactDataPhone> cachedContacts = new SortedListOf<ContactDataPhone>();
		manager.navigateTo().printPhonesPage();		
		List<WebElement> rawLines = driver.findElements(By.xpath("//table[@id='view']//td"));
		List<WebElement> names = driver.findElements(By.xpath("//table[@id='view']//td/b"));
		for (int i = 0; i < names.size(); i++) {
			WebElement rawLine = rawLines.get(i);
			WebElement name = names.get(i);
			String nameStr = name.getText();
			
			//System.out.println("NAME : " + nameStr);
			//if (nameStr.startsWith(" ")) System.out.println("    STARTS");
			//if (nameStr.endsWith(" ")) System.out.println("    ENDS");
			//String[] list = nameStr.split(" ");
			//String lastnames = list.length > 0 ? list[0] : "";
			//String firstnames = list.length > 1 ? list[1] : "";
		
			String rawStr = rawLine.getText();
			String mobilePhone = extractSubstring(rawStr, "M");
			String homePhone = extractSubstring(rawStr, "H");
			String workPhone = extractSubstring(rawStr, "W");
			cachedContacts.add(new ContactDataPhone()
				.withName(nameStr.trim())
				.withHome(homePhone)
				.withWork(workPhone)
				.withMobile(mobilePhone));	
		}
	this.cachedContactPhones = cachedContacts;
	}
	
	private String extractSubstring(String rawStr, String prefix) {
		Pattern pattern = Pattern.compile("(" + prefix + ": [a-zA-Z_0-9\\-]+)");
        Matcher matcher = pattern.matcher(rawStr);
        if (matcher.find()) {
            return matcher.group().substring((prefix + ":" + " ").length());
        }
        else {
        	return "";
        }		
	}

	public ContactHelper createContact(ContactData contact) {
		manager.navigateTo().mainPage();
    	initContactCreation();
		fillContactForm(contact, CREATION);
    	submitContactCreation();
    	manager.navigateTo().mainPage();
		manager.getModel().addContact(contact);
    	//rebuildCacheContacts(Type.NameMailsPhones);
    	return this;
	}

    public ContactHelper modifyContact(int index, ContactData contact) {
        Logger.getGlobal().info("contact: " + contact);
        Logger.getGlobal().info("modify:  " + manager.getModel().getContacts().get(index));
        manager.navigateTo().mainPage();
        initContactModification(index);
        fillContactForm(contact, MODIFICATION);
        submitContactModification();
        manager.navigateTo().mainPage();
        manager.getModel().removeContact(index).addContact(contact);
        //rebuildCacheContacts(Type.NameMailsPhones);
        return this;
    }

    public int modifyContactByUiIndex(int uiIndex, ContactData newContact) {
        manager.navigateTo().mainPage();
        String contactId = initContactMod(uiIndex);
        int modelIndex = findContactModelIndex(contactId);
        fillContactForm(newContact, MODIFICATION);
        submitContactModification();
        manager.navigateTo().mainPage();
        Logger.getGlobal().info("contact: " + newContact);
        Logger.getGlobal().info("modify:  " + manager.getModel().getContacts().get(modelIndex));
        manager.getModel().removeContact(modelIndex).addContact(newContact);
        return modelIndex;
    }

    public ContactHelper deleteContact(int index) {
		manager.navigateTo().mainPage();
		initContactModification(index);
		submitContactDeletion();
		manager.navigateTo().mainPage();
		manager.getModel().removeContact(index);
		//rebuildCacheContacts(Type.NameMailsPhones);
		return this;
	}
	
	//-------------------------------------------------------------------------------------------

    private int findContactModelIndex(String contactId) {
        List<ContactData> list = manager.getModel().getContacts();
        for (int i = 0; i < list.size(); i++) {
            if (contactId.equals(list.get(i).getId())) {
                return i;
            }
        }
        Assert.fail("Unable to find a contact with id [" + contactId + "]");
        return -1;
    }

	public ContactHelper initContactCreation() {
		manager.navigateTo().mainPage();
		click(By.linkText("add new"));
		return this;
	}

	public ContactHelper fillContactForm(ContactData contact, boolean formType) {
		type(By.name("firstname"), contact.getFirstname());
		type(By.name("lastname"), contact.getLastname());
		type(By.name("address"), contact.getAddress());
		type(By.name("home"), contact.getHome());
		type(By.name("mobile"), contact.getMobile());
		type(By.name("work"), contact.getWork());
		type(By.name("email"), contact.getEmail());
		type(By.name("email2"), contact.getEmail2());
	    selectByText(By.name("bday"), contact.getBday());
	    selectByText(By.name("bmonth"), contact.getBmonth());
		type(By.name("byear"), contact.getByear());
		
//		if (formType == CREATION) {
//			//selectByText("new_group", contact.getGroupname());	
//		} else {
//			if (driver.findElements(By.name("new_group")).size() != 0)	{
//				throw new Error ("Group selector exists in contact modification group!");
//			}
//		}		
	    
		type(By.name("address2"), contact.getAddress2());
		type(By.name("phone2"), contact.getPhone2());
		return this;
	}

	public ContactHelper submitContactCreation() {
		click(By.name("submit"));
		//cachedContacts = null;
		return this;
	}

    public ContactHelper initContactModification(int index) {
        manager.navigateTo().mainPage();
        click(By.xpath("(//a[contains(@href,'edit.php?')])["+ (index + 1) + "]"));
        return this;
    }

    public String initContactMod(int index) {
        manager.navigateTo().mainPage();
        click(By.xpath("(//a[contains(@href,'edit.php?')])["+ (index + 1) + "]"));
        String id = driver.findElement(By.name("id")).getAttribute("value");
        return id;
    }

    public ContactHelper submitContactModification() {
		click(By.xpath("//input[@value='Update']"));
		//cachedContacts = null;
		return this;
	}
	
	private ContactHelper submitContactDeletion() {
		click(By.xpath("//input[@value='Delete']"));
		//cachedContacts = null;
		return this;
	}
	
	public ContactHelper returnFromPrintPage() {
		//driver.get("http://localhost/addressbookv4.1.4/");
		//Properties properties = this.manager.properties; 
		manager.getProperty("baseUrl");
		//driver.get(properties.getProperty("baseUrl"));
		return this;
	}

}
